package modes

import (
	"fmt"
	"time"
)

/*消息通知表*/
type StudenMsg struct {
	Id      int64  `json:"id" xorm:"id"`           //id
	UId     int64  `json:"u_id" xorm:"u_id"`       //学员ID
	KcId    int64  `json:"kc_id" xorm:"kc_id"`     //课次ID
	Status  int64  `json:"status" xorm:"status"`   //是否已读 0 未读 1已读
	Type    string `json:"type" xorm:"type"`       //消息类型
	Title   string `json:"title" xorm:"title"`     //消息标题
	Contact string `json:"contact" xorm:"contact"` //消息描述
	At      int64  `json:"at" xorm:"at"`           //创建时间
}

func (this *StudenMsg) TableName() string {
	return "studen_msg"
}
func (this *StudenMsg) Save() (int64, error) {
	return Db(0).Insert(this)
}

func (this *StudenMsg) Get() (bool, error) {
	return Db(0).Get(this)
}
func (this *StudenMsg) delete(where string) (int64, error) {
	return Db(0).Where(where).Delete(this)
}
func (this *StudenMsg) Del() (int64, error) {
	where := fmt.Sprintf("id =%d", this.Id)
	return this.delete(where)
}
func (this *StudenMsg) Count(where string) (int64, error) {
	var val StudenMsg
	return Db(0).Where(where).Count(&val)
}
func (this *StudenMsg) update(where string, field string) (int64, error) {
	return Db(0).Where(where).Cols(field).Update(this)
}

func (this *StudenMsg) IdSet(field string) (int64, error) {
	where := fmt.Sprintf("id = %d", this.Id)
	return this.update(where, field)
}

func (this *StudenMsg) where(fage, count, page int, where, field string) ([]StudenMsg, error) {
	list := make([]StudenMsg, 0)
	var err error
	if field == "" {
		field = "id"
	}
	if 0 == fage { // 从小到大排序
		err = Db(0).Where(where).
			Asc(field).
			Limit(count, page*count).
			Find(&list)
	} else { // 从大到小排序
		err = Db(0).Where(where).
			Desc(field).
			Limit(count, page*count).
			Find(&list)
	}
	return list, err
}
func (this *StudenMsg) List(val *Pager) error {
	val.TName = this.TableName()
	w := fmt.Sprintf("uid = %d ", this.UId)
	val.Total, _ = this.Count(w)
	list, err := this.where(val.Rules, val.Count, val.Page-1, w, "")
	if err == nil {
		val.List = list
	}
	return err
}
func (this *StudenMsg) MyMsgList() ([]StudenMsg, error) {
	w := fmt.Sprintf("u_id = %d and type='%s' and at>%d  and at<%d ", this.UId, this.Type, this.At, time.Now().Unix())
	list := make([]StudenMsg, 0)
	err := Db(0).Where(w).
		Desc("at").Find(&list)
	return list, err
}
func (this *StudenMsg) MyNoReadMsgCount() (int64, error) {
	w := fmt.Sprintf("u_id = %d and at<%d and status=0 ", this.UId, time.Now().Add(time.Minute*30).Unix())
	i, err := Db(0).Table(this.TableName()).Where(w).Desc("at").Count()
	return i, err
}

func (this *StudenMsg) MyYuyueIdList() ([]int64, error) {
	w := fmt.Sprintf("u_id = %d and type='%s' and at>%d and ck_id>0 ", this.UId, this.Type, time.Now().Unix())
	list := make([]int64, 0)
	err := Db(0).Select("kc_id").Distinct("kc_id").Where(w).
		Desc("at").Find(&list)
	return list, err
}

func (this *StudenMsg) TypeNewList() ([]StudenMsg, error) {
	sql := fmt.Sprintf("SELECT t.type,any_value(t.u_id) u_id,any_value(t.title) title,any_value(t.contact) contact,any_value(t.at ) at FROM (SELECT * FROM studen_msg where u_id=%d and at<%d ORDER BY at DESC limit 50 ) t GROUP BY t.type", this.UId, time.Now().Add(time.Minute*30).Unix())
	list := make([]StudenMsg, 0)
	err := Db(0).SQL(sql).Find(&list)
	return list, err
}

func (this *StudenMsg) UpdateRead() {
	this.Status = 1
	Db(0).Table(this.TableName()).Where("u_id=? and at<=?", this.UId, time.Now().Add(time.Minute*30).Unix()).Cols("status").Update(this)
}

func (this *StudenMsg) SaveList(list []StudenMsg) error {
	const BatchSize = 100

	items := []StudenMsg{}
	for _, rId := range list {
		items = append(items, rId)
	}
	for n := 0; ; n++ {
		end := (n + 1) * BatchSize
		if end >= len(items) {
			end -= (end - len(items))
		}

		_, err := Db(0).Table(this.TableName()).Insert(items[n*BatchSize : end])
		if err != nil {
			return err
		}

		if end >= len(items) {
			break
		}
	}
	return nil

}

func (this *StudenMsg) KcIdSet(field string) (int64, error) {
	where := fmt.Sprintf("kc_id = %d and title='%s' ", this.KcId, this.Title)
	i, err := this.update(where, field)
	return i, err
}
